home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / c_news / 10 / database / dtest.c < prev    next >
C/C++ Source or Header  |  1988-08-09  |  6KB  |  230 lines

  1. /* dtest.c -- Program to test BPLUS database file index module shareware.
  2.  
  3.     Written by Arnold Cherdak for Turbo C, Version 1.5
  4.  
  5.     This program exercises the BPLUS module to index, retrieve, and add
  6.     records to the FAMILIES database.  It then produces the Main Street
  7.     Report.
  8.  
  9. */
  10. #include <bplus.h>      /* this is part of the BPLUS product */
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <conio.h>
  14. #include <fcntl.h>
  15. #include <sys\stat.h>
  16. #include <ctype.h>
  17. #include <string.h>
  18. #include <io.h>
  19.  
  20. #define TRIM 0  /* TRIM=1 for uniform length keys; =0 for min. length keys */
  21. #define TRIMLENGTH 24
  22. #define FILERR  "\nCAN'T OPEN DATABASE FILE!\n"
  23. #define FILERR2 "\nDATABASE FILE ERROR!\n"
  24. #define ADDKEYERR "\nERROR ADDING KEY TO INDEX!\n"
  25. #define OPENIXERR "\nERROR OPENING INDEX FILE!\n"
  26. #define CLOSEIXERR "\nERROR CLOSING INDEX FILE!\n"
  27. #define READERR "\nERROR READING DATABASE FILE!\n"
  28. #define UPPER 1
  29. #define LOWER 2
  30.  
  31. struct FAMILY_TYPE     /* database file record structure */
  32.     {
  33.     char name[25];
  34.     char street[25];
  35.     char street_num[10];
  36.     char other_data[68];
  37.     char linefeed;
  38.     char nulbyte;
  39.     };
  40.  
  41.  
  42. /**************************************************************************/
  43.                void scrub(char *s, int uplow, char *dest)
  44. /**************************************************************************/
  45. /* This function cleans up a string and returns it in a destination string.
  46.    Leading and trailing blanks are removed, the case is changed to all
  47.    upper, lower, or mixed case depending upon the value of parameter, uplow,
  48.    being 1, 2, or 0, respectively.  Internal blanks are limited to no more
  49.    than one in a sequence.  The source string is not changed.
  50. */
  51. {
  52.     char *st,c;
  53.     int i,j,flag;
  54.  
  55.     for(; s[0] == ' '; s++);  /* trim leading blanks */
  56.  
  57.     /* Copy characters to destination, converting to destination case and
  58.        limiting runs of blanks to one.
  59.     */
  60.     i = j = flag = 0;
  61.     while((c = s[i++]) != '\0')
  62.         {
  63.         if(uplow == UPPER)                 /* case becomes UPPER */
  64.             c = toupper(c);
  65.         else if(uplow == LOWER)               /* case becomes LOWER */
  66.             c = tolower(c);
  67.                                    /* or, case stays as it was */
  68.  
  69.         if(c == ' ')
  70.             {
  71.             if(flag != 1)         /* flag sez this is first blank */
  72.                 {
  73.                 flag = 1;
  74.                 dest[j++] = c;
  75.                 }
  76.             }
  77.         else                        /* character is not a blank */
  78.             {
  79.             flag = 0;
  80.             dest[j++] = c;
  81.             }
  82.         }
  83.  
  84. #if TRIM
  85.     if(j < TRIMLENGTH)
  86.         for(i=j;i<TRIMLENGTH;i++)   /* make sure all indices are same length */
  87.             dest[i] = ' ';
  88.     dest[TRIMLENGTH] = '\0';         /* terminate the destination string */
  89. #else
  90.     dest[j] = '\0';                /* terminate the destination string */
  91.     if(dest[--j] == ' ')           /* get rid of trailing blank */
  92.         dest[j] = '\0';
  93. #endif
  94. } /* end scrub */
  95.  
  96.  
  97. /**************************************************************************/
  98.                              void main()
  99. /**************************************************************************/
  100. {
  101. union    {
  102.         struct FAMILY_TYPE family;
  103.         char family_buffer[256];
  104.         } db;
  105.  
  106. ENTRY e;
  107. IX_DESC idx;      /* index file variable */
  108. int i;
  109. FILE *dbfil;
  110. long address;
  111. char str[130];
  112.  
  113.  
  114. /* start by opening the database file in text mode */
  115. if((dbfil = fopen("families.dat", "r")) == NULL)
  116.     {
  117.     /* error...can't open database file */
  118.     printf(FILERR);
  119.     exit();
  120.     }
  121.  
  122.  
  123. /* Next, create an index file using the street name field as the key.
  124.     The file name is families.idx
  125.     We will allow duplicate keys.
  126.  
  127.     Now create the index file using 'make_index()'
  128. */
  129. if(make_index("families.idx", &idx, 1) != IX_OK)
  130.     exit();
  131.  
  132.  
  133. /* Read through the database file, obtain the key and record number for each
  134.     record, and install them in the index file using 'add_index()'.
  135. */
  136. address = 0L;              /* pointer to first record in file */
  137. printf("\n");              /* home the cursor */
  138. while(fgets(&db.family_buffer, 255, dbfil) != (char *) NULL)
  139.     {
  140.     /* clean up messy key & put into structure for add_key. */
  141.     for(i=0;i<25;i++)
  142.         str[i] = db.family.street[i];
  143.  
  144.    /* terminate the string */
  145.     str[25] = '\0';
  146.  
  147.    /* trim leading & trailing blanks & reduce to single interior blanks. */
  148.     scrub(str, UPPER, e.key);
  149.  
  150.     /* display what goes into the index file just for grins... */
  151.     printf("KEY: %-25s ADDRESS: %4ld\n",e.key,address);
  152.  
  153.    /* current record address in database file */
  154.     e.recptr = address;
  155.  
  156.    /* add key to index file */
  157.     if(add_key(&e, &idx) != IX_OK)
  158.         /* add_key failed */
  159.         {
  160.         printf(ADDKEYERR);
  161.         exit();
  162.         }
  163.  
  164.    /* File pointer is already pointing to next record...get the address. */
  165.     address = ftell(dbfil);
  166.     }
  167.  
  168.  
  169. /* Now close the index file to flush the file buffer.  I don't really
  170.    know if this is necessary since I don't know how BPLUS maintains the
  171.    file buffer.  However, this will make sure that the whole index file is
  172.    written to disk.
  173. */
  174. if(close_index(&idx) != IX_OK)
  175.     {
  176.     printf(CLOSEIXERR);
  177.     exit();
  178.     }
  179.  
  180.  
  181. /* Re-open the index */
  182. if(open_index("families.idx", &idx, 1) != IX_OK)
  183.     {
  184.     printf(OPENIXERR);
  185.     exit();
  186.     }
  187.  
  188.  
  189. /*
  190.    Search for records having Main Street as the street name and print them
  191.    to stdout.  We may have to settle for less than a 100% match on the key
  192.    so just look for the first name, 'MAIN'.
  193.  
  194.    Since index file isn't sorted, we need to examine each index entry to
  195.    determine if it contains the substring, 'MAIN'.  If it does, print the
  196.    database record and loop back to get the next index record.  Continue
  197.    until the end-of-file for the index.
  198. */
  199. first_key(&idx);     /* point to first key in index file */
  200. while(next_key(&e, &idx) == IX_OK)
  201.     {
  202.     /* A nice Turbo-C function to find substrings...Gosh! Just like BASIC! */
  203.     if(strstr(e.key, "MAIN") != NULL)
  204.         /* a match is found */
  205.         {
  206.         /* Position the database file pointer to the record */
  207.         if(fseek(dbfil, e.recptr, SEEK_SET) != 0)
  208.             /* file error */
  209.             {
  210.             printf(FILERR2);
  211.             exit();
  212.             }
  213.  
  214.         /* read a record from the database file and place in family buffer */
  215.         if(fgets(&db.family_buffer, 255, dbfil) == (char *) NULL)
  216.             /* read error */
  217.             {
  218.             printf(READERR);
  219.             exit();
  220.             }
  221.  
  222.         /* got the record, now print it */
  223.         db.family_buffer[60] = '\0';       /* keeps the printout on screen */
  224.         printf("\n%s",db.family_buffer);
  225.         }
  226.  
  227.     } /* OK, go back for another... */
  228.  
  229. } /* end DTEST */
  230.